<?php
/**
 * 二次元データを扱うクラス.
 * @example griddata
 * @code
 * $test_array = array(
 *                     0=>array(0=>"あああ",1=>"いいい"),
 *                     1=>array(0=>"ううう",1=>"eeee")
 *                     );
 *
 * $obj = new griddata();
 * $obj->setData($test_array);
 *
 * while($obj->fetchRow()) {
 *   $col = array();
 *     while($aaa = $obj->fetchCol()) {
 *       echo "col:$aaa\n";
 *     }
 * }
 *
 * echo "------------------\n";
 * $obj->fetchInit();
 * while ($line = $obj->fetchRow()) {
 *   print_r($line);
 * }
 * @endcode
 */
class griddata {

  /**
   * コンストラクタ.
   */
  public function __construct() { $this->init(); }

  /**
   * init.
   * @see __construct()
   */
  public function init() {
    $this->data_array_ = array();
    $this->max_line_num_ = -1;
    $this->fetchInit();
  }

  /**
   * @name accessor method
   * @{
   */
  /**
   * パース後データのセッタ.
   * セットされたデータの要素数も保持.
   * @param array $d
   */
  public function setData($d) {
    $this->data_array_   = $d;
    $this->max_line_num_ = count($this->data_array_);
  }

  /**
   * パース後データのゲッタ.
   * XXX 処理が重くなるため、極力使わないほうがいいです.
   * @return array
   */
  public function getData() { return $this->data_array_; }

  // -----------------------------------------------------------------------

  /**
   * 指定行のデータを返す.
   * 存在しない行を指定された場合は、falseを返す.
   * @param int $i
   * @return array | false
   */
  public function getLine($i = -1) {

    // 指定がなければfetchのコンソール行を返す
    if (-1 == $i) {
      $i = $this->getPosRow();
    }
    // 行データを返す
    if (isset($this->data_array_[$i])) {
      return $this->data_array_[$i];
    } else {
      return false;
    }
  }

  /**
   * 指定カラムのデータを返す.
   * 存在しないカラムを指定された場合は、falseを返す.
   * @param int $row
   * @param int $col
   * @return array | false
   */
  public function getPos($row = -1, $col = -1) {

    // 指定がなければfetchのコンソール行を返す
    if (-1 == $row) {
      $row = $this->getPosRow();
    }
    if (-1 == $col) {
      $col = $this->getPosCol();
    }

    // カラムのデータを返す
    if (isset($this->data_array_[$row][$col])) {
      return $this->data_array_[$row][$col];
    } else {
      return false;
    }
  }

  /**
   * 最大行数を返す.
   * @return int
   */
  public function getMaxRow() { return $this->max_line_num_; }
  /**@}end of accessor method */

  /**
   * @name 'Fetch' Pointer init method
   * @{
   */
  /**
   * ポインタを初期化.
   * @subpackage fetch用 init メソッド群
   */
  public function fetchInit() {
    $this->fetchInitRow();
    $this->fetchInitCol();
  }
  /**
   * 行のポインタを初期化.
   * @subpackage fetch用 init メソッド群
   */
  public function fetchInitRow() {
    $this->pos_row_ = -1;
  }
  /**
   * カラムのポインタを初期化.
   * @subpackage fetch用 init メソッド群
   */
  public function fetchInitCol() {
    $this->pos_col_ = -1;
  }
  /**@} end of 'Fetch' Pointer init method*/

  /**
   * @name 'Fetch' Pointer handling method
   * ポインタ操作メソッド郡
   * @{ start of ポインタ操作メソッド郡
   *
   */
  /**
   * 行を1つ進めます.
   * @subpackage fetch用 ポインタ操作メソッド群
   */
  public function incPosRow() { $this->pos_row_++; }
  /**
   * カラムを1つ進めます.
   * @subpackage fetch用 ポインタ操作メソッド群
   */
  public function incPosCol() { $this->pos_col_++; }
  /**
   * 現在の行位置を取得.
   * @subpackage fetch用 ポインタ操作メソッド群
   * @return int
   */
  public function getPosRow() { return $this->pos_row_; }
  /**
   * 現在のカラム位置を取得.
   * @subpackage fetch用 ポインタ操作メソッド群
   * @return int
   */
  public function getPosCol() { return $this->pos_col_; }
  /**@} end of 'Fetch' Pointer handling method*/

  /**
   * 行データを返す.
   * fetchのメイン処理です.
   * @return mixed
   */
  public function fetchRow() {

    $this->incPosRow();

    // XXX 行数分ループしたら終了
    if ($this->getPosRow() > $this->getMaxRow()) {
      return false;
    }

    // 行を移動したら、列のポインタを初期化する.
    $this->fetchInitCol();

    return $this->getLine();
  }

  /**
   * 列のfetch.
   * @return mixed
   */
  public function fetchCol() {
    //カラムを1つ進める.
    $this->incPosCol();

    if (!(isset($this->data_array_[$this->getPosRow()][$this->getPosCol()]))) {
      return false;
    }
    return $this->data_array_[$this->getPosRow()][$this->getPosCol()];
  }

  /**
   * データ本体
   */
  private $data_array_;

  /**
   * データの全行数
   */
  private $max_line_num_;

  /**
   * 行ポインタ
   */
  private $pos_row_;

  /**
   * 列ポインタ
   */
  private $pos_col_;

}
//end of griddata class

//テストコード
//$test_array = array(
//0=>array(0=>"あああ",1=>"いいい"),
//1=>array(0=>"ううう",1=>"eeee")
//);
//
//$obj = new griddata();
//$obj->setData($test_array);
//
//while($obj->fetchRow()) {
//
//  $col = array();
//
//  while($aaa = $obj->fetchCol()) {
//
//    echo "col:$aaa\n";
//
//  }
//
//}
//
//echo "------------------\n";
//$obj->fetchInit();
//while ($line = $obj->fetchRow()) {
//  print_r($line);
//}


?>